package pers.leo.couplepointjava.rest;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import pers.leo.couplepointjava.core.consts.Constants;
import pers.leo.couplepointjava.core.consts.CpHistoryTypeEnum;
import pers.leo.couplepointjava.core.response.Result;
import pers.leo.couplepointjava.core.response.ResultController;
import pers.leo.couplepointjava.entity.CpHistory;
import pers.leo.couplepointjava.entity.CpPoint;
import pers.leo.couplepointjava.mapper.CpHistoryMapper;
import pers.leo.couplepointjava.mapper.CpPointMapper;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 分值历史记录控制器
 *
 * @author Leo
 * @since 2021/8/24
 */
@RestController
@RequestMapping(Constants.PREFIX_API + "history")
public class CpHistoryController extends ResultController {

    @Resource
    private CpHistoryMapper cpHistoryMapper;

    @Resource
    private CpPointMapper cpPointMapper;

    /**
     * 历史记录列表
     *
     * @param cpHistory 历史记录实体类
     * @return Result
     */
    @PostMapping("list")
    public Result list(CpHistory cpHistory) {
        List<CpHistory> historyList = cpHistoryMapper.selectList(new QueryWrapper<>(cpHistory));
//        return historyList.toString();
        return success(historyList);
    }

    /**
     * 增加分值
     *
     * @param cpHistory 历史记录实体类
     * @return Result
     */
    @PostMapping("add")
    public Result add(CpHistory cpHistory) {
        try {
            // verify
            cpHistory = verifyAndSetDefaultData(cpHistory, true);

            // get cpPoint
            CpPoint cpPoint = cpPointMapper.selectOne(new QueryWrapper<CpPoint>().eq("user_id", cpHistory.getUserId()));

            // insert history
            boolean success = updatePoint(cpPoint, true) && cpHistoryMapper.insert(cpHistory) == 1;

            return decide(success);
        } catch (Exception e) {
            return failure(e.getMessage());
        }
    }

    /**
     * 减少分值
     *
     * @param cpHistory 历史记录实体类
     * @return Result
     */
    @PostMapping("subtract")
    public Result subtract(CpHistory cpHistory) {
        try {
            // verify
            cpHistory = verifyAndSetDefaultData(cpHistory, false);

            // get cpPoint
            CpPoint cpPoint = cpPointMapper.selectOne(new QueryWrapper<CpPoint>().eq("user_id", cpHistory.getUserId()));

            // insert history
            boolean success = updatePoint(cpPoint, false) && cpHistoryMapper.insert(cpHistory) == 1;

            return decide(success);
        } catch (Exception e) {
            return failure(e.getMessage());
        }
    }

    /**
     * 验证并设置默认数据
     *
     * @param cpHistory 历史记录实体类
     * @param add       类型是否为添加 - 0
     * @return CpHistory 实体类
     * @throws NullPointerException 参数不能为空
     */
    private CpHistory verifyAndSetDefaultData(CpHistory cpHistory, boolean add) throws NullPointerException {
        // verify
        if (cpHistory != null && cpHistory.getUserId() == null) {
            cpHistory.setUserId(Constants.DEFAULT_USER_ID);
        }
        if (cpHistory != null && cpHistory.getContent() == null) {
            cpHistory.setContent(add ? Constants.DEFAULT_ADD_CONTENT : Constants.DEFAULT_SUBTRACT_CONTENT);
        }
        if (cpHistory == null) throw new NullPointerException("参数不能为空");

        // set default data
        // TODO: 2021/8/25 set default id
        cpHistory.setType(add ? CpHistoryTypeEnum.ADD.getType() : CpHistoryTypeEnum.SUBTRACT.getType());
        cpHistory.setCreateTime(LocalDateTime.now());
        return cpHistory;
    }

    /**
     * 更新分值
     *
     * @param cpPoint 分值实体类
     * @param add     类型是否为添加 - 0
     * @return boolean
     * @throws NullPointerException 未知用户
     */
    private boolean updatePoint(CpPoint cpPoint, boolean add) throws NullPointerException {
        // verify
        if (cpPoint == null) throw new NullPointerException("未知用户");
        // set point
        cpPoint.setPoint(add ? cpPoint.getPoint() + 1 : cpPoint.getPoint() - 1);
        // update cpPoint
        return cpPointMapper.updateById(cpPoint) == 1;
    }

}
